package com.qkl.user.utils;

import java.security.SecureRandom;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class UniqueRandomUtils {
    // 线程安全的缓存，存储已生成的值（按业务类型区分，避免全局冲突）
    private static final ConcurrentMap<String, Set<String>> CACHE = new ConcurrentHashMap<>();

    // 安全随机数生成器（比Random更安全，适合生成密码等敏感信息）
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();

    // 默认字符集：数字+大小写字母（62个字符）
    public static final String DEFAULT_CHAR_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    // 数字字符集
    public static final String NUMERIC_CHAR_SET = "0123456789";

    // 私有构造器，禁止实例化
    private UniqueRandomUtils() {}

    /**
     * 生成不重复的随机字符串
     * @param length 长度（必须>0）
     * @param charSet 字符集（如传null则使用默认字符集）
     * @param bizType 业务类型（用于区分不同场景的缓存，避免重复）
     * @return 随机字符串
     */
    public static String generateRandomString(int length, String charSet, String bizType) {
        if (length <= 0) {
            throw new IllegalArgumentException("长度必须大于0");
        }
        String actualCharSet = (charSet == null || charSet.isEmpty()) ? DEFAULT_CHAR_SET : charSet;
        if (actualCharSet.length() == 0) {
            throw new IllegalArgumentException("字符集不能为空");
        }

        // 初始化业务类型的缓存
        CACHE.putIfAbsent(bizType, new HashSet<>());
        Set<String> cacheSet = CACHE.get(bizType);

        // 生成随机字符串，直到不重复为止（最多尝试100次，避免死循环）
        int maxRetry = 100;
        String result;
        do {
            if (maxRetry-- <= 0) {
                throw new RuntimeException("生成不重复随机字符串失败，可能长度过小或字符集不足");
            }
            result = generateRandomString(length, actualCharSet);
        } while (!cacheSet.add(result)); // add成功表示不存在重复

        return result;
    }

    /**
     * 生成不重复的随机数字（纯数字字符串，避免long类型长度限制）
     * @param length 数字长度（必须>0且<=18，超过18位可能超出long范围）
     * @param bizType 业务类型
     * @return 随机数字字符串
     */
    public static String generateRandomNumber(int length, String bizType) {
        if (length <= 0 || length > 18) {
            throw new IllegalArgumentException("数字长度必须在1-18之间");
        }
        // 调用字符串生成方法，指定数字字符集
        return generateRandomString(length, NUMERIC_CHAR_SET, bizType);
    }

    /**
     * 清除某个业务类型的缓存（如定期清理过期数据）
     * @param bizType 业务类型
     */
    public static void clearCache(String bizType) {
        CACHE.remove(bizType);
    }

    /**
     * 内部方法：生成随机字符串（不保证唯一性）
     */
    private static String generateRandomString(int length, String charSet) {
        StringBuilder sb = new StringBuilder(length);
        int charSetLength = charSet.length();
        for (int i = 0; i < length; i++) {
            // 从字符集中随机选取一个字符
            int index = SECURE_RANDOM.nextInt(charSetLength);
            sb.append(charSet.charAt(index));
        }
        return sb.toString();
    }
}
